﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework;
using System.Runtime.InteropServices;
/*
namespace Textures
{
    public struct DDSHeader
    {
        public int Size;
        public HeaderFlags HeaderFlags;
        public int Height;
        public int Width;
        public int PitchOrLinearSize;
        public int Depth;
        public int MipMapCount;
        //11
        public int[] Reserved1;
        public DDSPixelFormat PixelFormat;
        public SurfaceFlags SurfaceFlags;
        public CubemapFlags CubemapFlags;
        //3
        public int[] Reserved2;
    }
    public struct DDSPixelFormat
    {
        public int Size;
        public PixelFormatFlags Flags;
        public string FourCC;
        public int RGBBitCount;
        public int RBitMask;
        public int GBitMask;
        public int BBitMask;
        public int ABitMask;
    }
    [Flags]
    public enum PixelFormatFlags
    {
        None = 0,
        //Texture contains alpha data; dwRGBAlphaBitMask contains valid data.
        AlphaPixels = 0x1,
        //Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data)
        Alpha = 0x2,
        //Texture contains compressed RGB data; dwFourCC contains valid data.
        FourCC = 0x4,
        //Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwRBitMask, dwRBitMask) contain valid data.
        RGB = 0x40,
        //Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask)
        YUV = 0x200,
        //Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file.
        Luminace = 0x20000,
    }
    [Flags]
    public enum HeaderFlags
    {
        None = 0,
        //Required in every .dds file.
        Caps = 0x1,
        //Required in every .dds file.
        Height = 0x2,
        //Required in every .dds file.
        Width = 0x4,
        //Required when pitch is provided for an uncompressed texture.
        Pitch = 0x8,
        //Required in every .dds file.
        PixelFormat = 0x1000,
        //Required in a mipmapped texture.
        MipMapCount = 0x20000,
        //Required when pitch is provided for a compressed texture.
        LinearSize = 0x80000,
        //Required in a depth texture.
        Depth = 0x80000
    }
    [Flags]
    public enum SurfaceFlags
    {
        None = 0,
        //Indicates that this surface contains alpha-only information
        Alpha = 0x2,
        //Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture).
        Complex = 0x8,
        //Optional; should be used for a mipmap.
        MipMap = 0x400000,
        //Required
        Texture = 0x1000,
    }

    [Flags]
    public enum CubemapFlags
    {
        None = 0,
        //Required for a cube map.
        Cubemap = 0x200,
        //Required when these surfaces are stored in a cube map.
        PositiveX = 0x400,
        //Required when these surfaces are stored in a cube map.
        NegativeX = 0x800,
        //Required when these surfaces are stored in a cube map.
        PositiveY = 0x1000,
        //Required when these surfaces are stored in a cube map.
        NegativeY = 0x2000,
        //Required when these surfaces are stored in a cube map.
        PositiveZ = 0x4000,
        //Required when these surfaces are stored in a cube map.
        NegativeZ = 0x8000,
        //Required for a volume texture.
        Volume = 0x200000,
    }
    public class DDSSuport
    {
        public static Texture Load(GraphicsDevice dev, Stream stream, int fileSize = 0)
        {
            DDSHeader header;
            fileSize = fileSize - 32 * 4;
            BinaryReader bin = new BinaryReader(stream);
            bin.ReadInt32();
            header.Size = bin.ReadInt32();
            header.HeaderFlags = (HeaderFlags)bin.ReadInt32();
            header.Height = bin.ReadInt32();
            header.Width = bin.ReadInt32();
            header.PitchOrLinearSize = bin.ReadInt32();
            header.Depth = bin.ReadInt32();
            header.MipMapCount = bin.ReadInt32();
            header.Reserved1 = new int[11];
            for(int i=0; i < 11; i++)
                header.Reserved1[i]= bin.ReadInt32();
            header.PixelFormat.Size = bin.ReadInt32();
            header.PixelFormat.Flags = (PixelFormatFlags)bin.ReadInt32();

            header.PixelFormat.FourCC = System.Text.ASCIIEncoding.ASCII.GetString(bin.ReadBytes(4)).Replace('\0', ' ').Trim();
            header.PixelFormat.RGBBitCount = bin.ReadInt32();
            header.PixelFormat.RBitMask = bin.ReadInt32();
            header.PixelFormat.GBitMask = bin.ReadInt32();
            header.PixelFormat.BBitMask = bin.ReadInt32();
            header.PixelFormat.ABitMask = bin.ReadInt32();
            header.SurfaceFlags = (SurfaceFlags)bin.ReadInt32();
            header.CubemapFlags = (CubemapFlags)bin.ReadInt32();
            header.Reserved2 = new int[3];
            for (int i = 0; i < 3; i++)
                header.Reserved2[i] = bin.ReadInt32();
            if (header.PixelFormat.Flags == PixelFormatFlags.FourCC)
            {
                if (header.CubemapFlags == CubemapFlags.None)
                {
                    Texture2D ret = new Texture2D(dev, header.Width, header.Height, false, (SurfaceFormat)Enum.Parse(typeof(SurfaceFormat), header.PixelFormat.FourCC, true));
                    byte[] data = bin.ReadBytes(header.PitchOrLinearSize > 0 ? header.PitchOrLinearSize : fileSize);
                    ((Texture2D)ret).SetData(data);
                    return ret;
                }
                else
                {
                    TextureCube ret = new TextureCube(dev, header.Width, false, (SurfaceFormat)Enum.Parse(typeof(SurfaceFormat), header.PixelFormat.FourCC, true));
                    byte[] data = bin.ReadBytes(header.PitchOrLinearSize > 0 ? header.PitchOrLinearSize : fileSize);

                    int size = header.Width * header.Height * 3 /2 ;
                    //int size = header.PitchOrLinearSize;
                    byte[] data1 = bin.ReadBytes(size);

                    ret.SetData(CubeMapFace.PositiveX, data1);
                    data1 = bin.ReadBytes(size);
                    ret.SetData(CubeMapFace.NegativeX, data1);
                    data1 = bin.ReadBytes(size);
                    ret.SetData(CubeMapFace.PositiveY, data1);
                    data1 = bin.ReadBytes(size);
                    ret.SetData(CubeMapFace.NegativeY, data1);
                    data1 = bin.ReadBytes(size);
                    ret.SetData(CubeMapFace.PositiveZ, data1);
                    data1 = bin.ReadBytes(size);
                    ret.SetData(CubeMapFace.NegativeZ, data1);
                    return ret;
                }
                
                
                return null;
            }
            else if(header.PixelFormat.Flags == PixelFormatFlags.Alpha)
            {
                var ret = new Texture2D(dev, header.Width, header.Height, header.MipMapCount > 0, SurfaceFormat.Alpha8);
                byte[] data = bin.ReadBytes(header.Width * header.Height);
                ret.SetData(data);
                
                return ret;
            } else
            {

                var ret = new TextureCube(dev, header.Width, false, SurfaceFormat.Color);
                int components = 3;
                if ((header.PixelFormat.Flags & PixelFormatFlags.AlphaPixels) == PixelFormatFlags.AlphaPixels)
                    components = 4;
                int size = header.Width * header.Height * components;
                //int size = header.PitchOrLinearSize;
                byte[] data1 = bin.ReadBytes(size);

                ret.SetData(CubeMapFace.PositiveX, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                data1 = bin.ReadBytes(size);
                ret.SetData(CubeMapFace.NegativeX, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                data1 = bin.ReadBytes(size);
                ret.SetData(CubeMapFace.PositiveY, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                data1 = bin.ReadBytes(size);
                ret.SetData(CubeMapFace.NegativeY, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                data1 = bin.ReadBytes(size);
                ret.SetData(CubeMapFace.PositiveZ, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                data1 = bin.ReadBytes(size);
                ret.SetData(CubeMapFace.NegativeZ, Enumerable.Range(0, size / components).Select(i => new Color(data1[i * components], data1[i * components + 1], data1[i * components + 2])).ToArray());
                return ret;
            }
            return null;
        }
    }
}
*/